package puzzle.model;


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


// This is a model class for the Photo domain.
public class PhotoModel {

    private String difficultiesFilePath;
    private List<Photo> photos;
    
    public PhotoModel(String difficultiesFilePath) {
        
        this.difficultiesFilePath = difficultiesFilePath;        
        
        photos = new ArrayList<Photo>();
        generatePhotos();
        
    }    

    // Retrieves photos from a txt file.
    // Stores them in an ArrayList.
    private void generatePhotos() {
        
        FileReader fr = null;
        BufferedReader br = null;

        try {            
            
            fr = new FileReader(difficultiesFilePath);
            br = new BufferedReader(fr);
            
            String line;
            while ( ((line = br.readLine()) != null ) && ( !line.isEmpty() ) ) {
                
                String[] elements = line.split(":");
                List<String> elementsList = new ArrayList<String>(Arrays.asList(elements)); 
                
                List<String> difficulties = elementsList.subList(1, elementsList.size());
                String photoName = elementsList.get(0);
                
                Photo nextPhoto = new Photo(photoName, difficulties);                    
                
                photos.add(nextPhoto); 
                
            }

        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        } finally {
            try {
                fr.close();
            } catch (IOException ioe) {
                 System.out.println(ioe.getMessage());
            }
        }
        
    }

    
    // Returns a list of all photos.
    public List<Photo> getAllPhotos() {
        return photos; 
    }
    
    
    // Returns a single photo.
    public Photo getPhoto(String name) {
        
        Photo photo = null;        
        for (Photo nextPhoto : photos) {
            if( nextPhoto.getName().equals(name) ) {
                photo = nextPhoto;
                break;
            }
        }        
        return photo;
        
    }  
    
    
    // Adds/Deletes/Replaces a difficulty for a selected photo.
    public List<String> changeDifficulty(String name, String newDifficulty, String oldDifficulty) {
        
        Photo thisPhoto = getPhoto(name);       
        List<String> currentDifficulties = thisPhoto.getDifficulties();
        
        // If a difficulty to be deleted is not in a current list it cannot be removes.
        // If a difficulty to be added is already in a current list is shouldn't be added again.
        List<String> newDifficulties = new ArrayList<String>();
        if ( ( oldDifficulty != null && !currentDifficulties.contains(oldDifficulty) ) ||
             ( newDifficulty != null && currentDifficulties.contains(newDifficulty ) ) ) {                 
            
            return newDifficulties;
        
        } else  {  
            
            if ( oldDifficulty != null ) {                   
                currentDifficulties.remove(oldDifficulty);
            }        
            
            // Add a difficulty in a proper place. So that they are sorted in terms of number of elements.
            if ( newDifficulty != null ) {            
                String[] newElements = newDifficulty.split("x");
            
                for(String thisDifficulty : currentDifficulties) {
                    String[] thisElements = thisDifficulty.split("x");                    
                    if( Integer.parseInt(newElements[0])*Integer.parseInt(newElements[1]) <= 
                        Integer.parseInt(thisElements[0])*Integer.parseInt(thisElements[1]) ) {
                        currentDifficulties.add(currentDifficulties.indexOf(thisDifficulty), newDifficulty); 
                        break;
                    }
                }
        
                if( !currentDifficulties.contains(newDifficulty) ) {
                    currentDifficulties.add(newDifficulty);
                }
            }
        
            newDifficulties = saveDifficulties(name, currentDifficulties);
            return newDifficulties;
        }
        
    }
    
    
    // Sets a new list of difficulties for a selected photo.
    // Also saves it in a txt file.
    private List<String> saveDifficulties(String name, List<String> labels) {
        
        Photo thisPhoto = getPhoto(name);        
        
        FileWriter fw = null;
        PrintWriter pw = null;

        try {
            
            // Set a new list of difficulties for a selected photo.
            thisPhoto.setDifficulties(labels);
            
            // Delete existing difficulties written in a txt file.
            fw = new FileWriter(difficultiesFilePath, false);
            pw = new PrintWriter(fw);
            pw.println();

            // Append difficulties from a new list.
            fw = new FileWriter(difficultiesFilePath, true);
            pw = new PrintWriter(fw);
            for (Photo photo : photos) {
                List<String> difficulties = photo.getDifficulties();
                String line = photo.getName();
                for (String level : difficulties) {
                    line += ":" + level;
                }                 
                pw.print(line);
                pw.println();
            }
            
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        } finally {
            try {
                fw.close();
            } catch (IOException ioe) {
                System.out.println(ioe.getMessage());
            }
        }
        
        return thisPhoto.getDifficulties();
        
    }   
    
    
}
